#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include "math.h"
#include <ctime>


#include "cv.h"
#include "highgui.h"
#include "common_defs.h"

#include "PointsDatabase.h"
#include "ImageDepthList.h"

#include "FigGroundQuizUI.h"
#include "SpatialFadeoutFilter.h"
#include "FlipColorFilter.h"

void FigGroundQuizUI::mouseCallback( int evt, int x, int y, int flags, void* vparam )
{
	FigGroundQuizUI* ui = (FigGroundQuizUI*)vparam;

	switch( evt )
	{
	case  CV_EVENT_LBUTTONDOWN:
		ui->m_click.x = x;
		ui->m_click.y = y;
		break;
	case CV_EVENT_MOUSEMOVE:
		ui->m_move.x = x;
		ui->m_move.y = y;
		break;
	}
}

FigGroundQuizUI::FigGroundQuizUI( ImageDepthList *imlist, PointsDatabase *pts )
{
	m_imlist = imlist;
	m_pts = pts;
}

FigGroundQuizUI::~FigGroundQuizUI(void)
{
	clearRandPts( m_randPts );
}

void FigGroundQuizUI::clearRandPts( vector<RandPtInfo*> randPts )
{
	for( int i = 0; i < randPts.size(); i++ )
	{
		if( randPts[i] ) delete randPts[i];
	}
	randPts.clear();
}
void FigGroundQuizUI::run()
{
	clearRandPts( m_randPts );

	for( PointsDatabase::iterator imIter = m_pts->begin(); imIter != m_pts->end(); imIter++ )
	{
		m_randPts.reserve( m_randPts.size() + imIter->second.size() );
		for( PointsDatabase::PointsInImage::iterator piter = imIter->second.begin(); piter != imIter->second.end(); piter++ )
		{
			m_randPts.push_back( new RandPtInfo( &(*piter), imIter ) );
		}
	}
	srand ( unsigned ( time (NULL) ) );
	random_shuffle( m_randPts.begin(), m_randPts.end() );

	int radius = 10;
	SpatialFadeoutFilter sfade( radius );
	FlipColorFilter flipcol( radius, true );
	
	IplImage* dispIm = cvCreateImage( cvSize(1600,800),IPL_DEPTH_8U, 3 );
	IplImage* filtIm = 0;

	display("main", dispIm, 1 );
	cvSetMouseCallback( "main", FigGroundQuizUI::mouseCallback, this );

	int numCorrect = 0;
	int numWrong = 0;
	ImageGroupData imdata;
	for( int pi = 0; pi < m_randPts.size(); pi++ )
	{
		m_click.x = -1;
		m_click.y = -1;
		m_move.x = -1;
		m_move.y = -1;

		ImageGroup* imgroup = m_imlist->find( m_randPts[pi]->imIter->first )->second;
		imdata.resetIfNewIm( imgroup );

		CvScalar bgcolor = flipcol.calcFlipColor( imdata, *imgroup, *m_randPts[pi]->pt );
		bgcolor.val[0] = ( bgcolor.val[0] + bgcolor.val[1] + bgcolor.val[2] ) / 3;
		bgcolor.val[1] = bgcolor.val[2] = bgcolor.val[0];

		if( !sfade.filter( imdata, *imgroup, *m_randPts[pi]->pt, bgcolor, &filtIm ) ) continue;

		CvPoint center = cvPoint(dispIm->width/2, dispIm->height/2 );


		while( m_click.x < 0 || m_click.y < 0 )
		{
			cvSet( dispIm, bgcolor );
			cvSetImageROI( dispIm, 
				cvRect( center.x - filtIm->width/2, center.y - filtIm->height/2,
					filtIm->width, filtIm->height ) );
			cvCopy( filtIm, dispIm );
			cvResetImageROI( dispIm );

			if( m_move.x > 0 && m_move.y > 0 )
			{
				int dx = m_move.x - center.x;
				int dy = m_move.y - center.y;

				double rad = atan2((double)-dy, (double)dx);
				drawArrow( dispIm, center, rad, 2*radius, 4*radius, CV_RGB(200,100,0), 1, 3 );
				drawArrow( dispIm, center, rad+PI/2, 2*radius, 2*radius+5, CV_RGB(200,100,0), 1, 0 );
				drawArrow( dispIm, center, rad-PI/2, 2*radius, 2*radius+5, CV_RGB(200,100,0), 1, 0 );
			}
			display("main", dispIm, 1 );
			cvWaitKey( 100 );
		}

		int dx = m_click.x - center.x;
		int dy = m_click.y - center.y;

		double rad = atan2((double)-dy, (double)dx);
		double figRad = m_randPts[pi]->pt->figRad;

		if( radianDifference<double>( rad, m_randPts[pi]->pt->figRad , 2*PI ) < PI/2.0 )
		{
			numCorrect++;
		}
		else
		{
			numWrong++;
		}
		printf("(%d) %d%%\n", (numCorrect + numWrong), numCorrect*100/(numCorrect + numWrong) );
	}
	cvReleaseImage( &dispIm );
	cvReleaseImage( &filtIm );
}